home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
set.h
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
15KB
|
613 lines
// $Id: set.h,v 1.3 1999/01/25 20:00:31 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#ifndef set_INCLUDED
#define set_INCLUDED
#include "config.h"
#include "assert.h"
#include "symbol.h"
class ShadowSymbol
{
public:
ShadowSymbol *next;
Symbol *symbol;
int pool_index;
inline NameSymbol *Identity() { return symbol -> Identity(); }
ShadowSymbol(Symbol *symbol_) : symbol(symbol_),
conflict(NULL)
{}
~ShadowSymbol() { delete conflict; }
Symbol *Conflict(int i) { return (*conflict)[i]; }
inline int NumConflicts()
{
return (conflict ? conflict -> Length() : 0);
}
inline void AddConflict(Symbol *conflict_symbol)
{
if ((symbol != conflict_symbol) && (! Find(conflict_symbol)))
conflict -> Next() = conflict_symbol;
return;
}
inline void RemoveConflict(int k)
{
int last_index = conflict -> Length() - 1;
if (k < 0) // when k is negative, it identifies the main symbol
symbol = (*conflict)[last_index];
else (*conflict)[k] = (*conflict)[last_index];
conflict -> Reset(last_index);
}
private:
Tuple<Symbol *> *conflict;
bool Find(Symbol *conflict_symbol)
{
if (! conflict)
conflict = new Tuple<Symbol *>(4);
for (int k = 0; k < conflict -> Length(); k++)
if ((*conflict)[k] == conflict_symbol)
return true;
return false;
}
};
class SymbolSet
{
public:
enum
{
DEFAULT_HASH_SIZE = 13,
MAX_HASH_SIZE = 1021
};
SymbolSet(int hash_size_ = DEFAULT_HASH_SIZE) : symbol_pool(256),
main_index(0),
sub_index(0)
{
hash_size = (hash_size_ <= 0 ? 1 : hash_size_);
prime_index = -1;
do
{
if (hash_size < primes[prime_index + 1])
break;
prime_index++;
} while (primes[prime_index] < MAX_HASH_SIZE);
base = (ShadowSymbol **) memset(new ShadowSymbol *[hash_size], 0, hash_size * sizeof(ShadowSymbol *));
}
~SymbolSet();
//
// Calculate the size of the set an return the value.
//
inline int Size()
{
int size = 0;
for (int i = 0; i < symbol_pool.Length(); i++)
{
ShadowSymbol *shadow = symbol_pool[i];
Symbol *symbol = shadow -> symbol;
for (int k = 0; symbol; symbol = (Symbol *) (k < shadow -> NumConflicts() ? shadow -> Conflict(k++) : NULL))
size++;
}
return size;
}
//
// Empty out the set in question - i.e., remove all its elements
//
inline void SetEmpty()
{
for (int i = 0; i < symbol_pool.Length(); i++)
delete symbol_pool[i];
symbol_pool.Reset();
base = (ShadowSymbol **) memset(base, 0, hash_size * sizeof(ShadowSymbol *));
}
//
// Empty out the set in question - i.e., remove all its elements
//
bool IsEmpty() { return symbol_pool.Length() == 0; }
//
// Assignment of a set to another.
//
SymbolSet &operator=(SymbolSet &rhs)
{
if (this != &rhs)
{
this -> SetEmpty();
this -> Union(rhs);
}
return *this;
}
//
// Equality comparison of two sets
//
bool operator==(SymbolSet &);
//
// NonEquality comparison of two sets
//
inline bool operator!=(SymbolSet &rhs)
{
return ! (*this == rhs);
}
//
// Union the set in question with the set passed as argument: "set"
//
void Union(SymbolSet &);
//
// Intersect the set in question with the set passed as argument: "set"
//
void Intersection(SymbolSet &);
//
// Return a bolean value indicating whether or not the set in question intersects the set passed as argument: "set"
// i.e., is there at least one element of set that is also an element of "this" set.
//
bool Intersects(SymbolSet &);
//
// How many elements with this name symbol do we have?
//
inline int NameCount(Symbol *element)
{
NameSymbol *name_symbol = element -> Identity();
for (ShadowSymbol *shadow = base[name_symbol -> index % hash_size]; shadow; shadow = shadow -> next)
{
if (shadow -> Identity() == name_symbol)
return shadow -> NumConflicts() + 1;
}
return 0;
}
//
// Is "element" an element of the set in question ?
//
inline bool IsElement(Symbol *element)
{
assert(element);
NameSymbol *name_symbol = element -> Identity();
for (ShadowSymbol *shadow = base[name_symbol -> index % hash_size]; shadow; shadow = shadow -> next)
{
if (shadow -> Identity() == name_symbol)
{
Symbol *symbol = shadow -> symbol;
for (int k = 0; symbol; symbol = (Symbol *) (k < shadow -> NumConflicts() ? shadow -> Conflict(k++) : NULL))
{
if (symbol == element)
return true;
}
return false;
}
}
return false;
}
//
// Add element to the set in question if was not already there.
//
inline void AddElement(Symbol *element)
{
NameSymbol *name_symbol = element -> Identity();
int i = name_symbol -> index % hash_size;
ShadowSymbol *shadow;
for (shadow = base[i]; shadow; shadow = shadow -> next)
{
if (shadow -> Identity() == name_symbol)
{
shadow -> AddConflict(element);
return;
}
}
shadow = new ShadowSymbol(element);
shadow -> pool_index = symbol_pool.Length();
symbol_pool.Next() = shadow;
shadow -> next = base[i];
base[i] = shadow;
//
// If the set is "adjustable" and the number of unique elements in it exceeds
// 2 times the size of the base, and we have not yet reached the maximum
// allowable size for a base, reallocate a larger base and rehash the elements.
//
if ((hash_size < MAX_HASH_SIZE) && (symbol_pool.Length() > (hash_size << 1)))
Rehash();
return;
}
void RemoveElement(Symbol *);
Symbol* FirstElement()
{
main_index = 0;
sub_index = 0;
return (main_index < symbol_pool.Length() ? symbol_pool[main_index] -> symbol : (Symbol *) NULL);
}
Symbol* NextElement()
{
Symbol *symbol = NULL;
if (main_index < symbol_pool.Length())
{
if (sub_index < symbol_pool[main_index] -> NumConflicts())
symbol = symbol_pool[main_index] -> Conflict(sub_index++);
else
{
main_index++;
sub_index = 0;
symbol = (main_index < symbol_pool.Length() ? symbol_pool[main_index] -> symbol : (Symbol *) NULL);
}
}
return symbol;
}
protected:
Tuple<ShadowSymbol *> symbol_pool;
int main_index,
sub_index;
ShadowSymbol **base;
int hash_size;
static int primes[];
int prime_index;
void Rehash();
};
//
// Single-value Mapping from a name_symbol into a symbol with that name.
//
class SymbolMap : public SymbolSet
{
public:
SymbolMap(int hash_size_ = DEFAULT_HASH_SIZE) : SymbolSet(hash_size_)
{}
//
// Is there an element with this name in the map ?
//
inline Symbol *Image(NameSymbol *name_symbol)
{
assert(name_symbol);
for (ShadowSymbol *shadow = base[name_symbol -> index % hash_size]; shadow; shadow = shadow -> n